home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Amiga Format CD 12
/
Amiga Format AFCD12 (Apr 1997, Issue 96).iso
/
-in_the_mag-
/
emulation
/
fs1541
/
disk.c
< prev
next >
Wrap
C/C++ Source or Header
|
1997-02-09
|
6KB
|
336 lines
/*
FS1541
disk.c
Basic disk interaction routines.
*/
#include <string.h>
#include <exec/types.h>
#include <exec/execbase.h>
#include <exec/memory.h>
#include <exec/ports.h>
#include <dos/dos.h>
#include <intuition/intuition.h>
#include <devices/timer.h>
#include <proto/exec.h>
#include <proto/intuition.h>
#include "disk.h"
#include "volume.h"
LONG numsofterrors = 0;
static struct MsgPort *diskport;
struct IOExtTD *diskreq;
BOOL autoscan = TRUE;
struct MsgPort *dpsender;
static UBYTE *diskimage;
static int diskscanned;
static BYTE sectab[683];
static int curblk = 357; /* Preloading starts at 18,0 = BAM */
static int devopen = 0;
ULONG chgcount;
static BOOL ignoreall, abortall;
struct IntuitionBase *IntuitionBase;
int wprotected;
static void cacheblock(ULONG n, BOOL write);
/*-------------------------------------------------------------------------*/
LONG InitDiskSS(STRPTR device, ULONG unit, ULONG flags)
{
LONG error = 0;
if((diskimage = AllocVec(D64_SIZE, MEMF_PUBLIC)))
{
if((diskport = CreateMsgPort()))
{
if((diskreq = CreateIORequest(diskport, sizeof(struct IOExtTD))))
{
if((devopen = (!OpenDevice(device,unit,(struct IORequest *)diskreq,flags))))
{
return(0);
} else error = ERROR_DEVICE_NOT_MOUNTED;
} else error = ERROR_NO_FREE_STORE;
} else error = ERROR_NO_FREE_STORE;
} else error = ERROR_NO_FREE_STORE;
QuitDiskSS();
return(error);
}
void QuitDiskSS(void)
{
if(devopen)
CloseDevice((struct IORequest*)diskreq);
if(diskreq)
DeleteIORequest(diskreq);
if(diskport)
DeleteMsgPort(diskport);
if(diskimage)
FreeVec(diskimage);
}
/*-------------------------------------------------------------------------*/
void ResetDisk(void)
{
diskscanned = !autoscan;
memset(sectab, SEC_NOT_LOADED, 683);
curblk = 357;
abortall = FALSE;
ignoreall = FALSE;
diskreq->iotd_Req.io_Command = TD_CHANGENUM;
diskreq->iotd_Req.io_Flags = IOF_QUICK;
DoIO((struct IORequest*)diskreq);
chgcount = diskreq->iotd_Req.io_Actual;
diskreq->iotd_Req.io_Command = ETD_CLEAR;
diskreq->iotd_Count = chgcount;
diskreq->iotd_Req.io_Flags = IOF_QUICK;
DoIO((struct IORequest*)diskreq);
diskreq->iotd_Req.io_Command = TD_PROTSTATUS;
diskreq->iotd_Req.io_Flags = IOF_QUICK;
DoIO((struct IORequest*)diskreq);
wprotected = diskreq->iotd_Req.io_Actual;
}
/* Asynchronous disk preloader */
BOOL LoadDisk(void)
{
if(!diskscanned && curvolumenode && autoscan)
{
int readblk;
for(readblk=curblk;readblk<683;readblk++)
if(sectab[readblk] == SEC_NOT_LOADED)
break;
if(readblk == 683)
{
if(curblk == 0)
{
/* Loading finished - switch off motor. */
diskreq->iotd_Req.io_Command = TD_MOTOR;
diskreq->iotd_Req.io_Flags = 0;
diskreq->iotd_Req.io_Length = 0;
DoIO((struct IORequest*)diskreq);
diskscanned = TRUE;
return(TRUE);
}
else
curblk = 0;
return(FALSE);
}
curblk = readblk;
cacheblock(readblk, FALSE);
return(FALSE);
} else return(TRUE);
}
void MotorOff(void)
{
if(diskscanned && CheckIO((struct IORequest*)UDStimer))
{
diskreq->iotd_Req.io_Command = ETD_UPDATE;
diskreq->iotd_Req.io_Flags = 0;
DoIO((struct IORequest*)diskreq);
diskreq->iotd_Req.io_Command = TD_MOTOR;
diskreq->iotd_Req.io_Flags = 0;
diskreq->iotd_Req.io_Length = 0;
DoIO((struct IORequest*)diskreq);
}
}
/*-------------------------------------------------------------------------*/
static LONG ts2block(UBYTE t, UBYTE s)
{
if(t<1)
{
return(-1);
}
else if(t<=17)
{
if(s>21)
return(-1);
else
return(21*(t-1) + s);
}
else if(t<=24)
{
if(s>19)
return(-1);
else
return(21*17 + 19*(t-18) + s);
}
else if(t<=30)
{
if(s>18)
return(-1);
else
return(21*17 + 19*7 + 18*(t-25) + s);
}
else if(t<=35)
{
if(s>17)
return(-1);
else
return(21*17 + 19*7 + 18*6 + 17*(t-31) + s);
}
else
return(-1);
}
struct DataBlock *getblock_ts(UBYTE t, UBYTE s)
{
LONG blk = ts2block(t, s);
if(blk>=0)
return(getputblock(blk, FALSE));
else
return(NULL);
}
struct DataBlock *putblock_ts(UBYTE t, UBYTE s, APTR data)
{
LONG blk = ts2block(t, s);
if(blk>=0)
{
CopyMem(data, diskimage+(blk*256), 256);
return(getputblock(blk, TRUE));
}
else
return(NULL);
}
struct DataBlock *getputblock(ULONG blk, BOOL write)
{
if(write)
cacheblock(blk, TRUE);
switch(sectab[blk])
{
case SEC_NOT_LOADED:
curblk = blk;
cacheblock(blk, FALSE);
if(sectab[blk] == SEC_OK)
return((struct DataBlock*)(diskimage+(blk*256)));
/* fall through */
case SEC_ERROR:
default:
{
static struct EasyStruct req =
{
sizeof(struct EasyStruct),
0,
"FS1541 Error",
"Volume %s has a\nread/write error on\nblock %ld.",
"Ignore|Ignore All|Abort All|Abort"
};
if(curvolumenode)
{
LONG num = -1;
if(abortall)
num = 0;
if(ignoreall)
num = 1;
if(num == -1 && (IntuitionBase = (struct IntuitionBase*)OpenLibrary("intuition.library",36)))
{
struct Process *pr;
if((dpsender->mp_Flags & PF_ACTION) != PA_SIGNAL
|| (pr = dpsender->mp_SigTask)->pr_Task.tc_Node.ln_Type != NT_PROCESS
|| pr->pr_WindowPtr != (APTR)-1)
{
ULONG args[2] = { (ULONG)&curvolumenode->name[1], blk };
num = EasyRequestArgs(NULL, &req, NULL, &args);
}
else
num = 0;
CloseLibrary((struct Library*)IntuitionBase);
}
switch(num)
{
case 3: default:
abortall = TRUE;
/* fall through */
case 0:
return(NULL);
case 2:
ignoreall = TRUE;
/* fall through */
case 1:
return((struct DataBlock*)(diskimage+(blk*256)));
}
}
return(NULL);
}
case SEC_OK:
return((struct DataBlock*)(diskimage+(blk*256)));
}
}
static void cacheblock(ULONG n, BOOL write)
{
diskreq->iotd_Count = chgcount;
diskreq->iotd_Req.io_Command = write ? ETD_WRITE : ETD_READ;
diskreq->iotd_Req.io_Flags = 0;
diskreq->iotd_Req.io_Data = diskimage+(n*256);
diskreq->iotd_Req.io_Offset = 256*n;
diskreq->iotd_Req.io_Length = 256;
if(!DoIO((struct IORequest*)diskreq))
sectab[n] = SEC_OK;
else
{
sectab[n] = SEC_ERROR;
numsofterrors++;
if(!curvolumenode)
{
/* Switch off the motor, unread/writable disk. */
diskreq->iotd_Req.io_Command = TD_MOTOR;
diskreq->iotd_Req.io_Flags = 0;
diskreq->iotd_Req.io_Length = 0;
DoIO((struct IORequest*)diskreq);
}
}
}